package com.zch.starter.opentelemetry.agent.mode.springboot.starter.config;


import com.zch.starter.opentelemetry.agent.mode.springboot.starter.interceptor.TraceIdInterceptor;
import com.zch.starter.opentelemetry.agent.mode.springboot.starter.interceptor.TraceInterceptorConfiguration;
import com.zch.starter.opentelemetry.agent.mode.springboot.starter.properties.ZchOpentelemetryProperties;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.SpanProcessor;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 类执行顺序：ConditionalOnProperty条件满足-->spring创建SentinelNacosAutoConfiguration实例--》spring
 * 创建SentinelNacosAutoConfigProperties-->spring 注入成员变量sentinelNacosAutoConfigProperties--》@PostConstruct
 * 方法执行--》@Bean方法执行
 */
@ConditionalOnProperty(prefix = "otel", name = "autoconfig.enabled", havingValue = "true", matchIfMissing = false)
@EnableConfigurationProperties(value = {ZchOpentelemetryProperties.class})
public class OpentelemetryAutoConfiguration {


    @Resource
    ZchOpentelemetryProperties zchOpentelemetryProperties;
    //spring 的环境上下文类
    @Resource
    Environment environment;

    /**
     * @PostConstruct 是指spring 创建好bean后 且属性被注入赋值结束后 才执行，他比里的@Bean 方法先执行
     *
     *
     * 属性设置完后 设置系统变量效果跟启动命令 JVM -D 一样的
     * 也可以在启动命令里做：https://github.com/alibaba/Sentinel/wiki/%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%E9%A1%B9
     * -Dproject.name=client-biz-test # 指定当前客户端的名称
     * -Dcsp.sentinel.dashboard.server=127.0.0.1:8080 # 指定远程的dashoard的地址。
     */
    @Deprecated// 没有用的，因为opentelemetry 的java agent 会在spring 容器初始化之前就读取了系统属性并完成了初始化
    @PostConstruct
    public void init() {
      /*  // 效果跟启动命令方式一样( -Dproject.name=***)
        System.setProperty("otel.traces.exporter", zchOpentelemetryProperties.getTraces().getExporter());
        System.setProperty("otel.metrics.exporter", zchOpentelemetryProperties.getMetrics().getExporter());
        System.setProperty("otel.logs.exporter", zchOpentelemetryProperties.getLogs().getExporter());
        System.setProperty("otel.service.name", zchOpentelemetryProperties.getService().getName());
        System.setProperty("otel.exporter.otlp.endpoint",zchOpentelemetryProperties.getExporter().getEndpoint());
        System.setProperty("otel.traces.sampler", zchOpentelemetryProperties.getTraces().getSampler());
        System.setProperty("otel.traces.sampler.arg", String.valueOf(zchOpentelemetryProperties.getTraces().getSamplerConfig().getArg()));*/

    }

    /**
     *  注意：
     *  1 因为是使用agent模式，OpenTelemetry bean 不需要初始化了,
     *  2 一定要使用全局的GlobalOpenTelemetry 来创建tracer 不然会导致 嵌套span 上下文切换混乱
     * @return
     */
    @Bean
    public Tracer tracer(){
        return GlobalOpenTelemetry.getTracer(environment.getProperty("spring.application.name"));
    }

    @Bean
    @ConditionalOnMissingBean
    public TraceIdInterceptor traceIdInterceptor(){
        return new TraceIdInterceptor();
    }
    @Bean
    @ConditionalOnMissingBean
    public TraceInterceptorConfiguration traceInterceptorConfiguration(TraceIdInterceptor traceIdInterceptor){
       return new TraceInterceptorConfiguration(traceIdInterceptor);
    }
}
